Let's post a message to Slack

In this session, we're going to use Python to post a message to Slack. I set up a team for us so we can mess around with the Slack API.

We're going to use a simple incoming webhook to accomplish this.

Hello API

API stands for "Application Programming Interface." An API is a way to interact programmatically with a software application.

If you want to post a message to Slack, you could open a browser and navigate to your URL and sign in with your username and password (or open the app), click on the channel you want, and start typing.

OR ... you could post your Slack message with a Python script.

Hello environmental variables

The code for this boot camp is on the public internet. We don't want anyone on the internet to be able to post messages to our Slack channels, so we're going to use an environmental variable to store our webhook.

The environmental variable we're going to use -- IRE_CFJ_2017_SLACK_HOOK -- should already be stored on your computer.

Python has a standard library module for working with the operating system called os. The os module has a data attribute called environ, a dictionary of environmental variables stored on your computer.

(Here is a new thing: Instead of using brackets to access items in a dictionary, you can use the get() method. The advantage to doing it this way: If the item you're trying to get doesn't exist in your dictionary, it'll return None instead of throwing an exception, which is sometimes a desired behavior.)


In [43]:
from os import environ

slack_hook = environ.get('IRE_CFJ_2017_SLACK_HOOK', None)

Hello JSON

So far we've been working with tabular data -- CSVs with columns and rows. Most modern web APIs prefer to shake hands with a data structure called JSON (JavaScript Object Notation), which is more like a matryoshka doll.

Python has a standard library module for working with JSON data called json. Let's import it.


In [37]:
import json

Using requests to post data

We're also going to use the requests library again, except this time, instead of using the get() method to get something off the web, we're going to use the post() method to send data to the web.


In [38]:
import requests

Formatting the data correctly

The JSON data we're going to send to the Slack webhook will start its life as a Python dictionary. Then we'll use the json module's dumps() method to turn it into a string of JSON.


In [42]:
# build a dictionary of payload data
payload = {
    'channel': '#general',
    'username': 'IRE Python Bot',
    'icon_emoji': ':ire:',
    'text': 'helllllllo!'
}

# turn it into a string of JSON
payload_as_json = json.dumps(payload)

Send it off to Slack


In [41]:
# check to see if you have the webhook URL
if slack_hook:

    # send it to slack!
    requests.post(slack_hook, data=payload_as_json)

else:

    # if you don't have the webhook env var, print a message to the terminal
    print("You don't have the IRE_CFJ_2017_SLACK_HOOK"
          " environmental variable")

Exercise

Read through the Slack documentation and post a message to a Slack channel ...

  • with a different emoji
  • with an image URL instead of an emoji
  • with a link in it
  • with an attachment
  • with other kinds of fancy formatting

Extra credit: Slack alert

Scenario: You cover the Fort Calhoun Nuclear Power Station outside of Omaha, Nebraska. Every day, you'd like to check an NRC website to see if your plant had any "Event Notifications" in the agency's most recent report. You decide to write a Slack script to do this for you. (Ignore, for now, the problem of setting up the script to run daily.)

Breaking down your problem, you need to:

  • Fetch the page with the latest reports using requests
  • Look through the text and see if your reactor's name appears in the page text (you could just use an if statement with in)
  • If it's there, use requests to send a message to Slack

Notice that we don't need to parse the page with BeautifulSoup -- we're basically just checking for the presence of a string inside a bigger string.

Extra, extra credit

Let's extend the script you just wrote with a function that would allow you to check for the presence of any string on an NRc page for any date of reports -- most days have their own page, though I think weekends are grouped together.

Let's break it down. Inside our function, we need to:

  • Figure out the URL pattern for each day's report page. Here's the page for Sept. 29, 2017
  • Decide how you want to accept the two arguments in your function -- one for the date and one for the string to search for (me, I'd use a date object for the default date argument to keep things explicit, but you could also pass a string)
  • Fill in the URL using format() and the date being passed to the function
  • Fetch the page using requests
  • Not every day has a page, so you'll need to check to see if the request was successful (hint: use the requests status_code attribute -- 200 means success)
  • If the request was successful, check for the presence of the string in the page text
  • If the text we're looking for is there, send a message to Slack

In [ ]: